//*********************************************************************************
//程序：AD0809LED.c
//功能：AT89C51+ADC0809电压测量显示程序(Keil uVision5+Proteus 7.8仿真通过)
//*********************************************************************************
#include <reg51.h>                                                                          /*包含头文件reg51.h */
#define uchar unsigned char                                                                 /*宏定义后方便书写*/
#define uint unsigned int                                                                   /*宏定义后方便书写*/
uchar code DigitSTARTable[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f}; //LED码表
uchar DisplayBuffer[4];                                                                     //显示码数据缓冲区
uchar AD_Data;                                                                              //AD0809原始数据
uint Temp;                                                                                  //处理后的数据
sbit START = P3 ^ 0;                                                                        //定义P3.0引脚位名称为START
sbit OE = P3 ^ 1;                                                                           //定义P3.1引脚位名称为OE
sbit EOC = P3 ^ 2;                                                                          //定义P3.2引脚位名称为EOC
sbit CLK = P3 ^ 3;                                                                          //定义P3.3引脚位名称为CLK
sbit ADDA = P3 ^ 4;                                                                         //定义P3.4引脚位名称为ADDA
sbit ADDB = P3 ^ 5;                                                                         //定义P3.5引脚位名称为ADDB
sbit ADDC = P3 ^ 6;                                                                         //定义P3.6引脚位名称为ADDC
sbit LED0 = P2 ^ 0;                                                                         //定义P2.0引脚位名称为LED0,选择LED的0位
sbit LED1 = P2 ^ 1;                                                                         //定义P2.1引脚位名称为LED1,选择LED的1位
sbit LED2 = P2 ^ 2;                                                                         //定义P2.2引脚位名称为LED2,选择LED的2位
sbit LED3 = P2 ^ 3;                                                                         //定义P2.3引脚位名称为LED3,选择LED的3位
sbit LED_DP = P1 ^ 7;                                                                       //定义P1.7引脚位名称为LED_DP,选择LED的DP位

//*********************************************************************************
//函数名：Delay
//函数功能：软件延时函数
//形式参数：uint i
//*********************************************************************************
void Delay(uint i)
{
  uint j;
  for (; i > 0; i--)
  {
    for (j = 0; j < 50; j++)
      ;
  }
}

//*********************************************************************************
//函数名：TimeInitial
//函数功能：定时器初始化函数 T0方式2，自动重装初值：10，定时：10us，
//信号周期T：20us 信号频率f：f=1/T=1000000/20=50 000HZ=50KHZ
//*********************************************************************************
void TimeInitial() //定时器初始化
{
  TMOD = 0x02; //定时器工作模式
  TH0 = 246;   //定时器初值高8位
  TL0 = 246;   //定时器初值低8位
  EA = 1;      //开总中断
  ET0 = 1;     //开定时器中断
  TR0 = 1;     //启动定时器
}

//*********************************************************************************
//函数名：Time0
//函数功能：定时器0中断服务子程序函数
//*********************************************************************************
void Time0(void) interrupt 1 using 0 //定时器中断服务子程序
{
  CLK = ~CLK; //产生AD0809工作脉冲：50KHZ
}

//*********************************************************************************
//函数名：Display
//函数功能：LED数码管显示函数
//*********************************************************************************
void Display()
{
  P1 = DigitSTARTable[DisplayBuffer[3]]; //取数据送P1端口显示（十位）
  LED0 = 0;                              // LED0管子开
  Delay(5);                              // 延时显示
  LED0 = 1;                              // LED0管子关
  P1 = DigitSTARTable[DisplayBuffer[2]]; //取数据送P1端口显示（个位）
  LED_DP = 1;                            // 小数点显示
  LED1 = 0;                              // LED1管子开
  Delay(5);                              // 延时显示
  LED1 = 1;                              // LED1管子关
  P1 = DigitSTARTable[DisplayBuffer[1]]; //取数据送P1端口显示 （小数1位）
  LED2 = 0;                              // LED2管子开
  Delay(5);                              // 延时显示
  LED2 = 1;                              // LED2管子关
  P1 = DigitSTARTable[DisplayBuffer[0]]; //取数据送P1端口显示（小数2位）
  LED3 = 0;                              // LED3管子开
  Delay(5);                              // 延时显示
  LED3 = 1;                              // LED3管子关
}

//*********************************************************************************
//函数名：main
//函数功能：主函数
//*********************************************************************************
void main()
{
  TimeInitial(); //启动定时器初化
  while (1)
  {
    ADDA = 0; //ADC0809通道选择,ABC都结GND也可以
    ADDB = 0;
    ADDC = 0;
    OE = 0; //输出关闭
    START = 0;
    START = 1; //START由低到高跳变（上跳沿），寄存器清零
    START = 0; //START由高到低跳变（下跳沿），启动AD转换
    while (EOC == 0)
      ;                                     //等待转换结束
    OE = 1;                                 //输出允许
    AD_Data = P0;                           //读ADC0809原始数据
    OE = 0;                                 //输出关闭
    Temp = (AD_Data * 1.0 / 255 * 5) * 100; //数据处理：输出值=输入值*5/255  参数5是基准电压5V
    DisplayBuffer[0] = Temp % 10;           //取处理后的数据个位，对应显示温度值的小数2位
    DisplayBuffer[1] = Temp / 10 % 10;      //取处理后的数据十位，对应显示温度值的小数1位
    DisplayBuffer[2] = Temp / 100 % 10;     //取处理后的数据百位，对应显示温度值的个位
    DisplayBuffer[3] = Temp / 1000;         //取处理后的数据千位，对应显示温度值的十位
    Display();                              //调用显示函数
  }
}
